(function($){

	$.imageTagging = function(element,options){
		var defaults = {
			onSaveTag: null,
			onDeleteTag:null,
			titleForm: "Enter a Description",
			saveLink: "Save Tag",
			tagsContainer:'.tags',
			selector:{
			    minHeight: 30,
			    minWidth:30,
			    maxWidth:150,
			    maxHeight:150
			}
		}
		
		var imageTagging = {};
		imageTagging.jqElement = $(element);
		imageTagging.dom = element;
		
		
		imageTagging.settings = {};
		imageTagging.tags = [];
		
		imageTagging.init = function(options){
			imageTagging.settings = $.extend(true, defaults, options);
			imageTagging.image = imageTagging.jqElement.find('img');
			 //Set the container equals to the image to tag
			imageTagging.jqElement.css({
			    width: imageTagging.image.width(),
			    height: imageTagging.image.height(),
			    position:'relative'
			}); 
			imageTagging.image.css({
			    top:0,
			    left:0,
			    position:'absolute',
			    zIndex:1
			}).selectable({
			    filter:'img',
			    stop: function(event, ui) {
				var hlp = $('.ui-selectable-helper');
				var posX = Math.abs(imageTagging.jqElement.offset().left - hlp.position().left);
				var posY = Math.abs(imageTagging.jqElement.offset().top - hlp.position().top);
				imageTagging.jqElement.find(".imageTagger-selector").remove();
				var sel = createSelector();           
				sel.css({
				    zIndex:2,
				    top:  posY - 5,
				    left: posX - 5,
				    height: ((hlp.height() < imageTagging.settings.selector.minHeight ? imageTagging.settings.selector.minHeight : hlp.height())) + "px",
				    width: (hlp.width() <  imageTagging.settings.selector.minWidth ? imageTagging.settings.selector.minWidth : hlp.width()) + "px"
				});
				sel.data('posX',posX);
				sel.data('posY',posY);
				imageTagging.jqElement.append(sel);
				createTagger(sel);
			    }
        		});

			//Public Functions
			imageTagging.getTags = function(){
				return imageTagging.tags;
			}

			//Private Functions
			var createSelector = function(){
			    var sel = $('<div />').addClass('imageTagger-selector');
			    sel.css({
				'position':'relative',
				'cursor':'move'
			    });
			    sel.draggable({
				iframeFix:true,
				containment:imageTagging.jqElement,
				refreshPositions: true
			    }).resizable({
				minHeight: imageTagging.settings.selector.minHeight,
				minWidth: imageTagging.settings.selector.minWidth,
				maxWidth: imageTagging.settings.selector.maxWidth,
				maxHeight: imageTagging.settings.selector.maxHeight,
				containment: 'parent',
				resize: function(event,ui){
				    var tagger = imageTagging.jqElement.find(".imageTagger-tagger");
				    var sel = imageTagging.jqElement.find(".imageTagger-selector");
				    tagger.css({
				        left: sel.width() + 5
				    });
				}
			    });

			    return sel;
			}; 

			var createTagger = function(obj){
			    var tagger = $('<div />').addClass('imageTagger-tagger');
			    tagger.css({
				position:'absolute',
				top: 0,
				left: obj.width() + 5
			    });

			    createForm(tagger);
			    obj.append(tagger);
			};

			var createForm = function(tagger){
			    var dform = $('<div />').addClass('imageTagger-form');
			    var close = $('<div />').addClass('imageTagger-form-close ui-icon ui-icon-circle-close').mouseover(function(){
				$(this).addClass('ui-state-hover');
			    }).mouseout(function(){
				$(this).removeClass('ui-state-hover');
			    }).click(function(){
				element.find('.imageTagger-selector').remove();
			    });
			    var p = $('<p />').html(imageTagging.settings.titleForm);
			    var input = $('<input type="text" />').attr('id','imageTagger-name-id');
			    var textarea = $('<textarea />').attr('id','imageTagger-description-id');
			    var linkSave = $('<a />').css({display:'block'}).attr('id','imageTagger-linksave').attr('href','javascript:;');
			    linkSave.unbind('click').click(function(){
				var obj_data = {
				    input: input.val(),
				    description: textarea.val(),
				    posX:imageTagging.jqElement.find(".imageTagger-selector").position().left,
				    posY:imageTagging.jqElement.find(".imageTagger-selector").position().top,
				    width:imageTagging.jqElement.find(".imageTagger-selector").width(),
				    height:imageTagging.jqElement.find(".imageTagger-selector").height()
				};
				var index = imageTagging.tags.length;
				imageTagging.tags.push(obj_data);

				var lnk_tag = $("<a />").addClass('imageTagger-tag').attr('href','javascript:;').html(obj_data.input).data('pos',obj_data).unbind('click').mouseover(function(){
				    drawTag($(this).data('pos'));
				}).mouseout(function(){
				    imageTagging.jqElement.find('.imageTagger-selector').remove();
				}).click(function(){
				    drawTag($(this).data('pos'));
				});

				var remove_tag = $("<div />").addClass('imageTagger-remove-tag ui-icon ui-icon-circle-close').mouseover(function(){
				    $(this).addClass('ui-state-hover');
				}).mouseout(function(){
				    $(this).removeClass('ui-state-hover');
				}).click(function(){
				    imageTagging.tags.splice(index,1);
				    $(this).parent().remove();
				    imageTagging.jqElement.find('.imageTagger-selector').remove(); 
				});

				lnk_tag.append(remove_tag);

				var holder = (typeof imageTagging.settings.tagsContainer == 'string' ? $(imageTagging.settings.tagsContainer) : imageTagging.settings.tagsContainer);
				holder.append(lnk_tag);
				holder.append("&nbsp;");


				if(imageTagging.settings.onSaveTag != null){
				    imageTagging.settings.onSaveTag.apply(this,obj_data);
				}

				imageTagging.jqElement.find('.imageTagger-selector').remove();
			    });
			    linkSave.text(imageTagging.settings.saveLink);
			    dform.append(close);
			    dform.append(p);
			    dform.append(input);
			    dform.append(textarea);
			    dform.append(linkSave);
			    tagger.append(dform);
			};

			var drawTag = function(data){
			    imageTagging.jqElement.find('.imageTagger-selector').remove();
			    var sel = $('<div />').addClass('imageTagger-selector');
			    sel.width(data.width).height(data.height).css({
				position:'absolute',
				top: data.posY,
				left: data.posX,
				zIndex: 2
			    });
			    imageTagging.jqElement.append(sel);
			    if(data.description != "")
				drawTagInfo(data);
			};

			var drawTagInfo = function(data){
			    var sel = imageTagging.jqElement.find('.imageTagger-selector');
			    var tagger = $('<div />').addClass('imageTagger-Info');
			    tagger.css({
				position:'absolute',
				top: -3,
				left: data.width + 5 
			    });
			    tagger.html(data.description);
			    sel.append(tagger);
			    imageTagging.jqElement.append(sel);
			};
	
			return this;
		};

		// fire up the plugin!
		return imageTagging.init(options);
	};

	$.fn.imageTagging = function(options){
		// cache the arguments
		args = Array.prototype.slice.call(arguments, 1);
		this.each(function(){
			if(undefined == $(this).data("imageTagging") && (typeof options === "object" || ! options)) {
				// create a new instance of cropzoom
				var imageTagging = new $.imageTagging(this, options);
				// in the jQuery version of the element
				// store a reference to the plugin object
				// you can later access the plugin and its methods and properties like
				// element.data('pluginName').publicMethod(arg1, arg2, ... argn) or
				// element.data('pluginName').settings.propertyName
				$(this).data("imageTagging", imageTagging);
				// chainability
				return this;
				
			} else if(undefined != $(this).data("imageTagging")[options]){
				// reload state from the element
				var imageTagging = $(this).data("imageTagging");
				// call public functions as $(element).imageTagging("publicFunction", args)
				return imageTagging[options].apply(this, args);
			} else {
				$.error("Method " +  options + " does not exist in jQuery.imageTagging");
				return this;
			}
		});
	};

})(jQuery);
